#include "Dispatcher.h"
#include <stdio.h>
#include <sys/epoll.h>
#include <stdlib.h>
#include <unistd.h>

#define MAX 520
struct EpollData
{
    int epfd;
    struct epoll_event* events;
};

//init--初始化
static void* epollInit();
//add
static int epollAdd(struct Channel* Channel, struct EventLoop* eventLoop);
//del
static int epollRemove(struct Channel* Channel, struct EventLoop* eventLoop);
//修改
static int epollModify(struct Channel* Channel, struct EventLoop* eventLoop);
//事件监测
static int epollDispatch(struct EventLoop* eventLoop, int timeout);//单位:s
//清除数据(关闭fd或者释放内存)
static int epollClear(struct EventLoop* eventLoop);
static int epollCtl(struct Channel* Channel, struct EventLoop* eventLoop, int op);

//全局变量
struct Dispatcher EpollDispatcher = {
    epollInit,
    epollAdd,
    epollRemove,
    epollModify,
    epollDispatch,
    epollClear
};

//init--初始化
static void* epollInit()
{
    struct EpollData* data = (struct EpollData*)malloc(sizeof(struct EpollData));
    data->epfd = epoll_create(1);//参数大于零即可，没有实际意义，这个函数的参数已经被废弃了
    if(data->epfd == -1)
    {
        perror("epoll_create");
        exit(0);
    }
    data->events = (struct epoll_event*)calloc(MAX, sizeof(struct epoll_event));//分配内存并初始化为0
    return data;
}

static int epollCtl(struct Channel* Channel, struct EventLoop* eventLoop, int op)
{
    struct EpollData* data = (struct EpollData*)eventLoop->dispatcherData;
    struct epoll_event ev;
    ev.data.fd = Channel->fd;
    int events = 0;
    if(Channel->events & ReadEvent)
    {
        events |= EPOLLIN;
    }
    //这里不能用else，因为读写事件可以同时存在
    if(Channel->events & WriteEvent)
    {
        events |= EPOLLOUT;
    }
    ev.events = events;
    int ret = epoll_ctl(data->epfd, op, Channel->fd, &ev);
    return ret;
}

//add
static int epollAdd(struct Channel* Channel, struct EventLoop* eventLoop)
{

    int ret = epollCtl(Channel, eventLoop, EPOLL_CTL_ADD);
    if(ret == -1)
    {
        perror("epoll_ctl add");
        exit(0);
    }
    return ret;
}
//del
static int epollRemove(struct Channel* Channel, struct EventLoop* eventLoop)
{
    int ret = epollCtl(Channel, eventLoop, EPOLL_CTL_DEL);
    if(ret == -1)
    {
        perror("epoll_ctl remove");
        exit(0);
    }
    //通过channel释放对应的TcpConnection资源
    Channel->destroyCallBack(Channel->arg);
    return ret;
}
//修改
static int epollModify(struct Channel* Channel, struct EventLoop* eventLoop)
{
    int ret = epollCtl(Channel, eventLoop, EPOLL_CTL_MOD);
    if(ret == -1)
    {
        perror("epoll_ctl modify");
        exit(0);
    }
    return ret;
}
//事件监测
static int epollDispatch(struct EventLoop* eventLoop, int timeout)//单位:s
{
    struct EpollData* data = (struct EpollData*)eventLoop->dispatcherData;
    int count = epoll_wait(data->epfd, data->events, MAX, timeout * 1000);//S转为MS
    if(count > 0)
    {
        printf("有新连接\n");
    }
    for(int idx = 0; idx < count; idx++)
    {
        int events = data->events[idx].events;
        int fd = data->events[idx].data.fd;
        //对端断开连接
        if(events & EPOLLERR || events & EPOLLHUP)
        {
            //对方断开连接，删除fd
            //epollRemove(Channel, eventLoop);
            continue;
        }
        if(events & EPOLLIN)//读事件
        {
            printf("读事件\n");
            eventActivate(eventLoop, fd, ReadEvent);
        }
        if(events & EPOLLOUT)//写事件
        {
            eventActivate(eventLoop, fd, WriteEvent);
        }
    }
    return 0;
}

//清除数据(关闭fd或者释放内存)
static int epollClear(struct EventLoop* eventLoop)
{
    struct EpollData* data = (struct EpollData*)eventLoop->dispatcherData;
    free(data->events);
    close(data->epfd);
    free(data);
    eventLoop->dispatcherData = NULL;
    return 0;
}

